package com.valuegroup.smarttodo.ui;

import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.alibaba.fastjson.JSON;
import com.valuegroup.smarttodo.R;
import com.valuegroup.smarttodo.data.ServiceFactory;
import com.valuegroup.smarttodo.data.model.Curriculum;
import com.valuegroup.smarttodo.data.model.Event;
import com.valuegroup.smarttodo.data.model.GoalRelate;
import com.valuegroup.smarttodo.data.model.Goals;
import com.valuegroup.smarttodo.data.model.Habit;
import com.valuegroup.smarttodo.data.model.HabitEvent;
import com.valuegroup.smarttodo.data.model.HabitOrder;
import com.valuegroup.smarttodo.data.model.HabitOrderRelate;
import com.valuegroup.smarttodo.data.model.Ideality;
import com.valuegroup.smarttodo.data.model.IdealityGrowHis;
import com.valuegroup.smarttodo.data.model.IdealityStage;
import com.valuegroup.smarttodo.data.model.Remark;
import com.valuegroup.smarttodo.data.model.Rethink;
import com.valuegroup.smarttodo.data.model.SearchHis;
import com.valuegroup.smarttodo.data.model.SumContent;
import com.valuegroup.smarttodo.data.model.SumTopic;
import com.valuegroup.smarttodo.data.model.Summarize;
import com.valuegroup.smarttodo.data.model.Tag;
import com.valuegroup.smarttodo.data.model.Task;
import com.valuegroup.smarttodo.data.model.TaskStep;
import com.valuegroup.smarttodo.data.service.BaseService;
import com.valuegroup.smarttodo.plugins.pickdialog.DateUtils;
import com.valuegroup.smarttodo.util.AlertUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import androidx.appcompat.app.AppCompatActivity;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class DataBackupActivity extends AppCompatActivity {

    @BindView(R.id.labShowStatus)
    TextView labShowStatus;
    @BindView(R.id.btnBackup)
    Button btnBackup;
    @BindView(R.id.btnRecover)
    Button btnRecover;

    private File externalStorageDir = Environment.getExternalStorageDirectory();
    private BaseService service;
    private File rootDir;
    private List<String> backupFileNames = new ArrayList<>();
    private List<File> backupFiles = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_data_backup);
        ButterKnife.bind(this);
        service = new BaseService();
    }

    @OnClick({R.id.btnBackup, R.id.btnRecover, R.id.btnInit, R.id.btnClear})
    public void onViewClicked(View view) {
        labShowStatus.setText("");
        createRootDir();

        switch (view.getId()) {
            case R.id.btnBackup:
                dataBackup();
                break;
            case R.id.btnRecover:
                dataRecover();
                break;
            case R.id.btnInit:
                dataInit();
                break;
            case R.id.btnClear:
                dataClear();
                break;
        }
    }

    private void dataClear() {
        AlertUtils.dialog(this, "将清空所有数据,且不可恢复", "确定", "取消", (dialog, which) -> {
            service.clearDBData();
        }, null);

    }

    private void dataInit() {
        AlertUtils.dialog(this, "将清空所有数据后,随机生成一些默认数据", "确定", "取消", (dialog, which) -> {
            service.clearDBData();
            ServiceFactory.getInstance().getDataInitService().initTaskListTestData();
            ServiceFactory.getInstance().getDataInitService().initHabitListTestData();
            ServiceFactory.getInstance().getDataInitService().initHabitOrderData();
            ServiceFactory.getInstance().getDataInitService().initGoalData();
            ServiceFactory.getInstance().getDataInitService().initCurriculumData();
            ServiceFactory.getInstance().getDataInitService().initTags();
        }, null);
    }

    private void dataRecover() {
        AlertUtils.dialog(this, "将清空现有的数据,从备份的文件中读取所有数据", "确定", "取消", (dialog, which) -> {
            service.clearDBData();
            readDataInBackupFile();
        }, null);
    }

    private void readDataInBackupFile() {
        readReadmeFile();
        for (File file : backupFiles) {
            printLog("开始恢复 >> " + file.getName());
            switch (file.getName().trim()) {
                case "Event.txt":
                    service.getEventDao().insertInTx(readBackupFile(file, Event.class));
                    break;
                case "Habit.txt":
                    service.getHabitDao().insertInTx(readBackupFile(file, Habit.class));
                    break;
                case "HabitEvent.txt":
                    service.getHabitEventDao().insertInTx(readBackupFile(file, HabitEvent.class));
                    break;
                case "HabitOrder.txt":
                    service.getHabitOrderDao().insertInTx(readBackupFile(file, HabitOrder.class));
                    break;
                case "HabitOrderRelate.txt":
                    service.getHabitOrderRelateDao().insertInTx(readBackupFile(file, HabitOrderRelate.class));
                    break;
                case "Ideality.txt":
                    service.getIdealityDao().insertInTx(readBackupFile(file, Ideality.class));
                    break;
                case "IdealityGrowHis.txt":
                    service.getIdealityGrowHisDao().insertInTx(readBackupFile(file, IdealityGrowHis.class));
                    break;
                case "IdealityStage.txt":
                    service.getIdealityStageDao().insertInTx(readBackupFile(file, IdealityStage.class));
                    break;
                case "Remark.txt":
                    service.getRemarkDao().insertInTx(readBackupFile(file, Remark.class));
                    break;
                case "SearchHis.txt":
                    service.getSearchHisDao().insertInTx(readBackupFile(file, SearchHis.class));
                    break;
                case "Tag.txt":
                    service.getTagDao().insertInTx(readBackupFile(file, Tag.class));
                    break;
                case "Task.txt":
                    service.getTaskDao().insertInTx(readBackupFile(file, Task.class));
                    break;
                case "TaskStep.txt":
                    service.getTaskStepDao().insertInTx(readBackupFile(file, TaskStep.class));
                    break;
                case "Goals.txt":
                    service.getGoalsDao().insertInTx(readBackupFile(file, Goals.class));
                    break;
                case "GoalRelate.txt":
                    service.getGoalRelateDao().insertInTx(readBackupFile(file, GoalRelate.class));
                    break;
                case "Curriculum.txt":
                    service.getCurriculumDao().insertInTx(readBackupFile(file, Curriculum.class));
                    break;
                case "Rethink.txt":
                    service.getRethinkDao().insertInTx(readBackupFile(file, Rethink.class));
                    break;
                case "SumContent.txt":
                    service.getSumContentDao().insertInTx(readBackupFile(file, SumContent.class));
                    break;
                case "Summarize.txt":
                    service.getSummarizeDao().insertInTx(readBackupFile(file, Summarize.class));
                    break;
                case "SumTopic.txt":
                    service.getSumTopicDao().insertInTx(readBackupFile(file, SumTopic.class));
                    break;

            }
        }
    }

    private void dataBackup() {
        printLog("开始备份数据");

        createDataFile("Event", service.getEventDao().loadAll());
        createDataFile("Habit", service.getHabitDao().loadAll());
        createDataFile("HabitEvent", service.getHabitEventDao().loadAll());
        createDataFile("HabitOrder", service.getHabitOrderDao().loadAll());
        createDataFile("HabitOrderRelate", service.getHabitOrderRelateDao().loadAll());
        createDataFile("Ideality", service.getIdealityDao().loadAll());
        createDataFile("IdealityGrowHis", service.getIdealityGrowHisDao().loadAll());
        createDataFile("IdealityStage", service.getIdealityStageDao().loadAll());
        createDataFile("Remark", service.getRemarkDao().loadAll());
        createDataFile("SearchHis", service.getSearchHisDao().loadAll());
        createDataFile("Tag", service.getTagDao().loadAll());
        createDataFile("Task", service.getTaskDao().loadAll());
        createDataFile("TaskStep", service.getTaskStepDao().loadAll());
        createDataFile("Goals", service.getGoalsDao().loadAll());
        createDataFile("GoalRelate", service.getGoalRelateDao().loadAll());
        createDataFile("Curriculum", service.getCurriculumDao().loadAll());
        createDataFile("Rethink", service.getRethinkDao().loadAll());
        createDataFile("SumContent", service.getSumContentDao().loadAll());
        createDataFile("Summarize", service.getSummarizeDao().loadAll());
        createDataFile("SumTopic", service.getSumTopicDao().loadAll());

        createReadmeFile();
    }

    public <T> List readBackupFile(File file, T cls) {
        List<T> result = new ArrayList<>();
        try {
            if (!file.exists()) {
                printLog(file.getName() + " >> 文件不存在,无法恢复备份!");
            }

            FileInputStream fis = new FileInputStream(file);
            InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8);
            BufferedReader br = new BufferedReader(isr);
            String json = null;
            while ((json = br.readLine()) != null) {
                if (!TextUtils.isEmpty(json)) {
                    result.add(JSON.parseObject(json, (Type) cls));
                }
            }

            printLog(file.getName() + " >> 读取完成");
            br.close();
            isr.close();
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    private void readReadmeFile() {
        File readme = new File(rootDir, "readme.txt");
        try {
            if (!readme.exists()) {
                printLog(readme.getPath() + " >> 文件不存在,无法恢复备份!");
            }

            FileInputStream fis = new FileInputStream(readme);
            InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8);
            BufferedReader br = new BufferedReader(isr);
            String fileName = null;
            while ((fileName = br.readLine()) != null) {
                if (!TextUtils.isEmpty(fileName)) {
                    File file = new File(rootDir, fileName);
                    backupFiles.add(file);
                }
            }

            printLog("readme.txt >> 读取完成");
            br.close();
            isr.close();
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void createReadmeFile() {
        File readme = new File(rootDir, "readme.txt");
        try {
            if (readme.exists()) {
                readme.delete();
            }
            readme.createNewFile();

            FileOutputStream fos = new FileOutputStream(readme);
            OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
            for (String e : backupFileNames) {
                osw.write(e);
                osw.write("\n");
            }
            printLog("写入完成 >> readme.txt");

            osw.flush();
            osw.close();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private <T> void createDataFile(String modelName, List<T> data) {
        printLog("---------");
        if (TextUtils.isEmpty(modelName)) {
            return;
        }

        String fileName = modelName + ".txt";
        backupFileNames.add(fileName);

        File jsonFile = new File(rootDir, fileName);
        printLog("开始备份 >> " + fileName);

        try {
            if (jsonFile.exists()) {
                printLog("删除旧的备份文件");
                jsonFile.delete();
            }

            jsonFile.createNewFile();
            printLog("创建新备份文件");

            FileOutputStream fos = new FileOutputStream(jsonFile);
            OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
            printLog("共有" + (data == null ? "0" : data.size()) + "条记录需要处理");
            for (T e : data) {
                osw.write(JSON.toJSONString(e));
                osw.write("\n");
            }
            printLog("备份完成 >> " + fileName);

            osw.flush();
            osw.close();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    private void createRootDir() {
        rootDir = new File(externalStorageDir, "SmartTodo" + File.separator + "backup" + File.separator + DateUtils.date2str(new Date(), DateUtils.F40));
        printLog(rootDir.getAbsolutePath());
        if (!rootDir.exists()) {
            printLog("创建存储目录成功");
            rootDir.mkdirs();
        } else {
            printLog("存储目录已创建");
        }
    }

    private void printLog(String str) {
        labShowStatus.setText(labShowStatus.getText() + "\n" + str);
    }
}
